package com.lkdont.android.media.examples.ui.audio

import android.Manifest
import android.annotation.SuppressLint
import android.media.MediaRecorder
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import com.lkdont.android.base.ui.BaseFrag
import com.lkdont.android.media.examples.R
import com.lkdont.android.media.examples.util.FileUtils
import kotlinx.android.synthetic.main.frag_record_audio.*
import java.io.IOException
import java.lang.IllegalStateException

/**
 * 录制音频
 *
 * @author lqd
 */
class RecordAudioFrag : BaseFrag() {

    companion object {

        private const val TAG = "RecordAudioFrag"

        private const val REQ_ID_PERMISSIONS = 101

        private val PERMISSIONS = arrayOf(
            Manifest.permission.RECORD_AUDIO
        )

    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(
            R.layout.frag_record_audio,
            container,
            false
        )
    }

    private var audioSampleRate: Int = 48 * 1000
    private var audioBitrate: Int = 64 * 1000
    private var audioChannelCount: Int = 2

    private var selectedEncodeFormat: String? = null
    private var selectedOutputFormat: String? = null

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // 请求相关权限
        requestPermissions(PERMISSIONS, REQ_ID_PERMISSIONS)
        // 初始化UI
        audioEncodeFormatSp.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {

            override fun onNothingSelected(parent: AdapterView<*>?) {
                selectedEncodeFormat = null
                updateInfoUi()
            }

            override fun onItemSelected(
                parent: AdapterView<*>?,
                view: View?,
                position: Int,
                id: Long
            ) {
                val items = resources.getStringArray(R.array.media_recorder_audio_encode_formats)
                selectedEncodeFormat = items[position]
                updateInfoUi()
            }
        }
        audioOutputFormatSp.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {

            override fun onNothingSelected(parent: AdapterView<*>?) {
                selectedOutputFormat = null
                updateInfoUi()
            }

            override fun onItemSelected(
                parent: AdapterView<*>?,
                view: View?,
                position: Int,
                id: Long
            ) {
                val items = resources.getStringArray(R.array.media_recorder_audio_output_formats)
                selectedOutputFormat = items[position]
                updateInfoUi()
            }
        }

        recordAudioBtn.setOnClickListener {
            when {
                mediaRecorder == null -> {
                    startRecording()
                }
                recordPausing -> {
                    resumeRecording()
                }
                !recordPausing -> {
                    pauseRecording()
                }
            }
            updateRecordUi()
        }

        stopRecordBtn.setOnClickListener {
            stopRecording()
            updateRecordUi()
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == REQ_ID_PERMISSIONS) {
            if (!hasPermissions(PERMISSIONS)) {
                // 没有获取到相关权限
                showMessage(R.string.no_permission)
                activity?.onBackPressed()
            }
        }
    }

    /*** 更新信息Ui */
    @SuppressLint("SetTextI18n")
    private fun updateInfoUi() {
        if (selectedEncodeFormat == null || selectedOutputFormat == null) {
            audioNameTv.text = null
            audioSampleRateTv.text = null
            audioBitRateTv.text = null
            audioChannelCountTv.text = null
            return
        }
        when (selectedEncodeFormat) {
            "AMR_NB" -> {
                // 支持4.75-12.2 kbps，采样率为 8 kHz
                audioSampleRate = 8 * 1000
                audioBitrate = 12200
                audioChannelCount = 1
            }
            "AMR_WB" -> {
                // 有 9 个比特率（介于 6.60-23.85 kbit/s 之间）可供选择，采样率为 16 kHz
                audioSampleRate = 16 * 1000
                audioBitrate = 23850
                audioChannelCount = 1
            }
            else -> {
                audioSampleRate = 48 * 1000
                audioBitrate = 64 * 1000
                audioChannelCount = 2
            }
        }
        audioSampleRateTv.text = "${audioSampleRate / 1000f}kHz"
        audioBitRateTv.text = "${audioBitrate / 1000f}kbps"
        audioChannelCountTv.text = "$audioChannelCount"
        // 文件名
        when {
            selectedEncodeFormat!!.contains("AMR") && (selectedOutputFormat == "MPEG_4" || selectedOutputFormat == ".aac") -> {
                // 编码格式与输出格式不匹配
                audioNameTv.text = null
                return
            }
            selectedEncodeFormat!!.contains("AAC") && selectedOutputFormat == ".amr" -> {
                // 编码格式与输出格式不匹配
                audioNameTv.text = null
                return
            }
            else -> {
                val name = "media-recorder-${selectedEncodeFormat}"
                val suffix = when (selectedOutputFormat) {
                    "THREE_GPP" -> ".3gp"
                    "MPEG_4" -> ".m4a"
                    else -> selectedOutputFormat
                }
                audioNameTv.text = "${name}${suffix}"
            }
        }
    }

    private fun updateRecordUi() {
        when {
            mediaRecorder != null -> {
                if (recordPausing) {
                    recordAudioBtn.text = "继续录制"
                } else {
                    recordAudioBtn.text = "暂停录制"
                }
                stopRecordBtn.visibility = View.VISIBLE
            }

            else -> {
                recordAudioBtn.text = "开始录制"
                stopRecordBtn.visibility = View.GONE
            }
        }
    }

    override fun onPause() {
        super.onPause()
        stopRecording()
        updateRecordUi()
    }

    //******************************** 录制音频 ********************************//

    private fun getAudioEncoder(): Int {
        return when (selectedEncodeFormat) {
            "AMR_NB" -> MediaRecorder.AudioEncoder.AMR_NB
            "AMR_WB" -> MediaRecorder.AudioEncoder.AMR_WB
            "AAC" -> MediaRecorder.AudioEncoder.AAC
            "HE_AAC" -> MediaRecorder.AudioEncoder.HE_AAC
            "AAC_ELD" -> MediaRecorder.AudioEncoder.AAC_ELD
            else -> throw IllegalStateException("不支持这个类型($selectedEncodeFormat)")
        }
    }

    private fun getAudioOutputFormat(): Int {
        return when (selectedOutputFormat) {
            "THREE_GPP" -> MediaRecorder.OutputFormat.THREE_GPP
            "MPEG_4" -> MediaRecorder.OutputFormat.MPEG_4
            ".amr" -> {
                when (selectedEncodeFormat) {
                    "AMR_NB" -> MediaRecorder.OutputFormat.AMR_NB
                    "AMR_WB" -> MediaRecorder.OutputFormat.AMR_WB
                    else -> throw IllegalStateException("不支持这个类型($selectedEncodeFormat)")
                }
            }
            ".aac" -> {
                MediaRecorder.OutputFormat.AAC_ADTS
            }
            else -> throw IllegalStateException("不支持这个类型($selectedOutputFormat)")
        }
    }

    private var mediaRecorder: MediaRecorder? = null

    private fun startRecording() {
        val fileName = audioNameTv.text.toString()
        if (fileName.isEmpty()) {
            showMessage("音频文件名为空，请检查参数设置")
            return
        }
        val file = FileUtils.getAudioCacheFile(requireContext(), fileName)
        if (file == null) {
            showMessage("获取音频输入路径失败")
            return
        }
        if (mediaRecorder != null) {
            stopRecording()
        }
        mediaRecorder = MediaRecorder().apply {
            // 1、首先设置数据源
            setAudioSource(MediaRecorder.AudioSource.DEFAULT)
            // 2、然后设置输出文件格式
            setOutputFormat(getAudioOutputFormat())
            // 3、最后设置其它参数
            setOutputFile(file.absolutePath)
            setAudioEncoder(getAudioEncoder())
            setAudioSamplingRate(audioSampleRate)
            setAudioEncodingBitRate(audioBitrate)
            setAudioChannels(audioChannelCount)
            try {
                // 4、准备录制器
                prepare()
            } catch (e: IOException) {
                Log.e(TAG, "startRecording: MediaRecorder prepare fail.")
            }
            // 5、开始录制
            start()
        }
        recordPausing = false
    }

    private var recordPausing = false

    private fun pauseRecording() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            if (mediaRecorder != null && !recordPausing) {
                recordPausing = true
                mediaRecorder?.pause()
            }
        } else {
            Log.w(TAG, "pauseRecording: 当前Android版本(${Build.VERSION.SDK_INT})不支持暂停功能")
        }
    }

    private fun resumeRecording() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            if (mediaRecorder != null && recordPausing) {
                mediaRecorder?.resume()
                recordPausing = false
            }
        } else {
            Log.w(TAG, "pauseRecording: 当前Android版本(${Build.VERSION.SDK_INT})不支持暂停功能")
        }
    }

    private fun stopRecording() {
        mediaRecorder?.apply {
            stop()
            release()
        }
        mediaRecorder = null
        recordPausing = false
    }
}